﻿///
/// Test script file NetworkAlgorithmAStarTest.fsx.
/// Test for NetworkAlgorithmAStar.fs
///

#load "Network.fs"
#load "NetworkAlgorithmAStar.fs"

#light

open System
open System.Text.RegularExpressions

open PathFinder.Network
open PathFinder.PathFindingAlgorithms.NetworkAlgorithmAStar

(* Tests for various network typologies *)

(* Randomizer *)
let rnd = new Random (1111)
let Randomizer min max =
    (* Getting the number of nodes to generate *)
    let rndv = rnd.Next (min, max)
    ()

(* Test type declaration *)
type NetworkTraversalTestDeclaration = {
    Category: string
    Name: string;
    Description: string;
    CorrectPath: string list;
    Active: bool;
    mutable Result: bool option
    }

(* Tests declaration *)
let test001 = {Category = "Simple forward-only networks"; Name = "Simple-1"; Description = ""; CorrectPath = ["Node A -> Node C -> Node D"]; Active = true; Result = None}
let test002 = {Category = "Simple forward-only networks"; Name = "Simple-2"; Description = ""; CorrectPath = ["Node A -> Node B -> Node C -> Node D"]; Active = true; Result = None}
let test003 = {Category = "Simple forward-only networks"; Name = "Simple-2.1"; Description = ""; CorrectPath = ["Node A -> Node B -> Node C -> Node D"]; Active = true; Result = None}
let test004 = {Category = "Simple forward-only networks"; Name = "Simple-3"; Description = ""; CorrectPath = ["Node A -> Node B -> Node E -> Node F -> Node D"]; Active = true; Result = None}
let test005 = {Category = "Simple looped networks"; Name = "Looped-1"; Description = ""; CorrectPath = ["Node A -> Node C -> Node D"]; Active = true; Result = None}
let test006 = {Category = "Simple looped networks"; Name = "Looped-2"; Description = ""; CorrectPath = ["Node A -> Node B -> Node C -> Node D -> Node E -> Node F"]; Active = true; Result = None}
let test007 = {Category = "Simple looped networks"; Name = "Looped-3"; Description = ""; CorrectPath = ["Node A -> Node D -> Node C -> Node B -> Node F"]; Active = true; Result = None}
let test008 = {Category = "Simple looped networks"; Name = "Looped-4"; Description = ""; CorrectPath = ["Node A -> Node B -> Node D"; "Node A -> Node C -> Node D"]; Active = true; Result = None}
let test009 = {Category = "Simple non-feasible networks"; Name = "NonFeas-1"; Description = ""; CorrectPath = []; Active = true; Result = None}
let test010 = {Category = "Simple non-feasible networks"; Name = "NonFeas-Looped-2"; Description = ""; CorrectPath = []; Active = true; Result = None}
let test011 = {Category = "Simple non-feasible networks"; Name = "NonFeas-Looped-3"; Description = ""; CorrectPath = []; Active = true; Result = None}
let test012 = {Category = "Simple non-feasible networks"; Name = "NonFeas-4"; Description = ""; CorrectPath = []; Active = true; Result = None}

(* Test collection *)
let tests = [test001; test002; test003; test004; test005; test006; test007; test008; test009; test010; test011; test012]

(* Utility functions *)
let PrintTest test =
    "Test \"" + test.Name + "\": Category" + test.Category + ", Description: " + test.Description
let PrintTestHeader test =
    printfn "************************************************************************************"
    printfn "Test: %s/%s" test.Category test.Name
    printfn "Description: %s" test.Description
    printfn "************************************************************************************"
    printfn "Logging actions:"
    ()
let CheckPath correct_paths path =
    match path with
    | "" -> List.isEmpty correct_paths
    | _ -> List.exists (fun x -> x = path) correct_paths

(* Test test001 *)
if test001.Active then
    PrintTestHeader test001
    printfn "Defining nodes..."
    let nodeA = new NetworkNode ("Node A")
    let nodeB = new NetworkNode ("Node B")
    let nodeC = new NetworkNode ("Node C")
    let nodeD = new NetworkNode ("Node D")
    printfn "Setting neighbourhood..."
    nodeA.AddNeighbour (nodeB, 1.0)
    nodeA.AddNeighbour (nodeC, 3.0)
    nodeB.AddNeighbour (nodeD, 10.0)
    nodeC.AddNeighbour (nodeD, 1.0)
    printfn "Network set! Listing nodes..."
    printfn "- Node -> %s" (nodeA.ToString ())
    printfn "- Node -> %s" (nodeB.ToString ())
    printfn "- Node -> %s" (nodeC.ToString ())
    printfn "- Node -> %s" (nodeD.ToString ())
    printfn "Working..."
    let res = AStar nodeA nodeD
    let path = (PrintPath "" (RebuildPath [] (snd res) nodeD.Name))
    let successful = CheckPath test001.CorrectPath path
    test001.Result <- Some successful
    printfn "Showing parental directions..."
    for KeyValue (k, v) in (snd res) do
        printfn "(child, pr) -> (%s, %s)" k v
    printfn "Test finished: Path: %s | Success? ==> %b" path successful

(* Test test002 *)
if test002.Active then
    PrintTestHeader test002
    printfn "Defining nodes..."
    let nodeA = new NetworkNode ("Node A")
    let nodeB = new NetworkNode ("Node B")
    let nodeC = new NetworkNode ("Node C")
    let nodeD = new NetworkNode ("Node D")
    let nodeE = new NetworkNode ("Node E")
    printfn "Setting neighbourhood..."
    nodeA.AddNeighbour (nodeB, 10.0)
    nodeB.AddNeighbour (nodeC, 3.0)
    nodeB.AddNeighbour (nodeE, 1.0)
    nodeC.AddNeighbour (nodeD, 1.0)
    nodeE.AddNeighbour (nodeD, 10.0)
    printfn "Network set! Listing nodes..."
    printfn "- Node -> %s" (nodeA.ToString ())
    printfn "- Node -> %s" (nodeB.ToString ())
    printfn "- Node -> %s" (nodeC.ToString ())
    printfn "- Node -> %s" (nodeD.ToString ())
    printfn "- Node -> %s" (nodeE.ToString ())
    printfn "Working..."
    let res = AStar nodeA nodeD
    let path = (PrintPath "" (RebuildPath [] (snd res) nodeD.Name))
    let successful = CheckPath test002.CorrectPath path
    test002.Result <- Some successful
    printfn "Showing parental directions..."
    for KeyValue (k, v) in (snd res) do
        printfn "(child, pr) -> (%s, %s)" k v
    printfn "Test finished: Path: %s | Success? ==> %b" path successful

(* Test test003 *)
if test003.Active then
    PrintTestHeader test003
    printfn "Defining nodes..."
    let nodeA = new NetworkNode ("Node A")
    let nodeB = new NetworkNode ("Node B")
    let nodeC = new NetworkNode ("Node C")
    let nodeD = new NetworkNode ("Node D")
    let nodeE = new NetworkNode ("Node E")
    printfn "Setting neighbourhood..."
    nodeA.AddNeighbour (nodeB, 10.0)
    nodeA.AddNeighbour (nodeD, 30.0)
    nodeB.AddNeighbour (nodeC, 3.0)
    nodeB.AddNeighbour (nodeE, 1.0)
    nodeC.AddNeighbour (nodeD, 1.0)
    nodeE.AddNeighbour (nodeD, 10.0)
    printfn "Network set! Listing nodes..."
    printfn "- Node -> %s" (nodeA.ToString ())
    printfn "- Node -> %s" (nodeB.ToString ())
    printfn "- Node -> %s" (nodeC.ToString ())
    printfn "- Node -> %s" (nodeD.ToString ())
    printfn "- Node -> %s" (nodeE.ToString ())
    printfn "Working..."
    let res = AStar nodeA nodeD
    let path = (PrintPath "" (RebuildPath [] (snd res) nodeD.Name))
    let successful = CheckPath test003.CorrectPath path
    test003.Result <- Some successful
    printfn "Showing parental directions..."
    for KeyValue (k, v) in (snd res) do
        printfn "(child, pr) -> (%s, %s)" k v
    printfn "Test finished: Path: %s | Success? ==> %b" path successful

(* Test test004 *)
if test004.Active then
    PrintTestHeader test004
    printfn "Defining nodes..."
    let nodeA = new NetworkNode ("Node A")
    let nodeB = new NetworkNode ("Node B")
    let nodeC = new NetworkNode ("Node C")
    let nodeD = new NetworkNode ("Node D")
    let nodeE = new NetworkNode ("Node E")
    let nodeF = new NetworkNode ("Node F")
    printfn "Setting neighbourhood..."
    nodeA.AddNeighbour (nodeB, 3.0)
    nodeB.AddNeighbour (nodeC, 1.0)
    nodeB.AddNeighbour (nodeE, 3.0)
    nodeC.AddNeighbour (nodeD, 30.0)
    nodeE.AddNeighbour (nodeD, 3.0)
    nodeE.AddNeighbour (nodeF, 1.0)
    nodeF.AddNeighbour (nodeD, 1.0)
    printfn "Network set! Listing nodes..."
    printfn "- Node -> %s" (nodeA.ToString ())
    printfn "- Node -> %s" (nodeB.ToString ())
    printfn "- Node -> %s" (nodeC.ToString ())
    printfn "- Node -> %s" (nodeD.ToString ())
    printfn "- Node -> %s" (nodeE.ToString ())
    printfn "- Node -> %s" (nodeF.ToString ())
    printfn "Working..."
    let res = AStar nodeA nodeD
    let path = (PrintPath "" (RebuildPath [] (snd res) nodeD.Name))
    let successful = CheckPath test004.CorrectPath path
    test004.Result <- Some successful
    printfn "Showing parental directions..."
    for KeyValue (k, v) in (snd res) do
        printfn "(child, pr) -> (%s, %s)" k v
    printfn "Test finished: Path: %s | Success? ==> %b" path successful

(* Test test005 *)
if test005.Active then
    PrintTestHeader test005
    printfn "Defining nodes..."
    let nodeA = new NetworkNode ("Node A")
    let nodeB = new NetworkNode ("Node B")
    let nodeC = new NetworkNode ("Node C")
    let nodeD = new NetworkNode ("Node D")
    printfn "Setting neighbourhood..."
    nodeA.AddNeighbour (nodeB, 1.0)
    nodeA.AddNeighbour (nodeC, 3.0)
    nodeB.AddNeighbour (nodeD, 10.0)
    nodeB.AddNeighbour (nodeA, 2.0)
    nodeC.AddNeighbour (nodeD, 1.0)
    nodeC.AddNeighbour (nodeA, 2.0)
    nodeD.AddNeighbour (nodeB, 2.0)
    nodeD.AddNeighbour (nodeC, 2.0)
    printfn "Network set! Listing nodes..."
    printfn "- Node -> %s" (nodeA.ToString ())
    printfn "- Node -> %s" (nodeB.ToString ())
    printfn "- Node -> %s" (nodeC.ToString ())
    printfn "- Node -> %s" (nodeD.ToString ())
    printfn "Working..."
    let res = AStar nodeA nodeD
    let path = (PrintPath "" (RebuildPath [] (snd res) nodeD.Name))
    let successful = CheckPath test005.CorrectPath path
    test005.Result <- Some successful
    printfn "Showing parental directions..."
    for KeyValue (k, v) in (snd res) do
        printfn "(child, pr) -> (%s, %s)" k v
    printfn "Test finished: Path: %s | Success? ==> %b" path successful

(* Test test006 *)
if test006.Active then
    PrintTestHeader test006
    printfn "Defining nodes..."
    let nodeA = new NetworkNode ("Node A")
    let nodeB = new NetworkNode ("Node B")
    let nodeC = new NetworkNode ("Node C")
    let nodeD = new NetworkNode ("Node D")
    let nodeE = new NetworkNode ("Node E")
    let nodeF = new NetworkNode ("Node F")
    printfn "Setting neighbourhood..."
    nodeA.AddNeighbour (nodeB, 10.0)
    nodeA.AddNeighbour (nodeF, 300.0)
    nodeB.AddNeighbour (nodeC, 10.0)
    nodeB.AddNeighbour (nodeF, 200.0)
    nodeC.AddNeighbour (nodeD, 10.0)
    nodeC.AddNeighbour (nodeF, 100.0)
    nodeD.AddNeighbour (nodeE, 10.0)
    nodeD.AddNeighbour (nodeF, 50.0)
    nodeE.AddNeighbour (nodeA, 10.0)
    nodeE.AddNeighbour (nodeF, 10.0)
    printfn "Network set! Listing nodes..."
    printfn "- Node -> %s" (nodeA.ToString ())
    printfn "- Node -> %s" (nodeB.ToString ())
    printfn "- Node -> %s" (nodeC.ToString ())
    printfn "- Node -> %s" (nodeD.ToString ())
    printfn "- Node -> %s" (nodeE.ToString ())
    printfn "- Node -> %s" (nodeF.ToString ())
    printfn "Working..."
    let res = AStar nodeA nodeF
    let path = (PrintPath "" (RebuildPath [] (snd res) nodeF.Name))
    let successful = CheckPath test006.CorrectPath path
    test006.Result <- Some successful
    printfn "Showing parental directions..."
    for KeyValue (k, v) in (snd res) do
        printfn "(child, pr) -> (%s, %s)" k v
    printfn "Test finished: Path: %s | Success? ==> %b" path successful

(* Test test007 *)
if test007.Active then
    PrintTestHeader test007
    printfn "Defining nodes..."
    let nodeA = new NetworkNode ("Node A")
    let nodeB = new NetworkNode ("Node B")
    let nodeC = new NetworkNode ("Node C")
    let nodeD = new NetworkNode ("Node D")
    let nodeE = new NetworkNode ("Node E")
    let nodeF = new NetworkNode ("Node F")
    printfn "Setting neighbourhood..."
    nodeA.AddNeighbour (nodeB, 500.0)
    nodeA.AddNeighbour (nodeE, 20.0)
    nodeA.AddNeighbour (nodeD, 50.0)
    nodeB.AddNeighbour (nodeA, 10.0)
    nodeB.AddNeighbour (nodeE, 20.0)
    nodeB.AddNeighbour (nodeC, 10.0)
    nodeB.AddNeighbour (nodeF, 10.0)
    nodeC.AddNeighbour (nodeD, 10.0)
    nodeC.AddNeighbour (nodeE, 20.0)
    nodeC.AddNeighbour (nodeB, 50.0)
    nodeD.AddNeighbour (nodeA, 10.0)
    nodeD.AddNeighbour (nodeE, 20.0)
    nodeD.AddNeighbour (nodeC, 50.0)
    printfn "Network set! Listing nodes..."
    printfn "- Node -> %s" (nodeA.ToString ())
    printfn "- Node -> %s" (nodeB.ToString ())
    printfn "- Node -> %s" (nodeC.ToString ())
    printfn "- Node -> %s" (nodeD.ToString ())
    printfn "- Node -> %s" (nodeE.ToString ())
    printfn "- Node -> %s" (nodeF.ToString ())
    printfn "Working..."
    let res = AStar nodeA nodeF
    let path = (PrintPath "" (RebuildPath [] (snd res) nodeF.Name))
    let successful = CheckPath test007.CorrectPath path
    test007.Result <- Some successful
    printfn "Showing parental directions..."
    for KeyValue (k, v) in (snd res) do
        printfn "(child, pr) -> (%s, %s)" k v
    printfn "Test finished: Path: %s | Success? ==> %b" path successful

(* Test test008 *)
if test008.Active then
    PrintTestHeader test008
    printfn "Defining nodes..."
    let nodeA = new NetworkNode ("Node A")
    let nodeB = new NetworkNode ("Node B")
    let nodeC = new NetworkNode ("Node C")
    let nodeD = new NetworkNode ("Node D")
    printfn "Setting neighbourhood..."
    nodeA.AddNeighbour (nodeB, 20.0)
    nodeA.AddNeighbour (nodeC, 20.0)
    nodeB.AddNeighbour (nodeA, 20.0)
    nodeB.AddNeighbour (nodeC, 20.0)
    nodeB.AddNeighbour (nodeD, 20.0)
    nodeC.AddNeighbour (nodeA, 20.0)
    nodeC.AddNeighbour (nodeB, 20.0)
    nodeC.AddNeighbour (nodeD, 20.0)
    printfn "Network set! Listing nodes..."
    printfn "- Node -> %s" (nodeA.ToString ())
    printfn "- Node -> %s" (nodeB.ToString ())
    printfn "- Node -> %s" (nodeC.ToString ())
    printfn "- Node -> %s" (nodeD.ToString ())
    printfn "Working..."
    let res = AStar nodeA nodeD
    let path = (PrintPath "" (RebuildPath [] (snd res) nodeD.Name))
    let successful = CheckPath test008.CorrectPath path
    test008.Result <- Some successful
    printfn "Showing parental directions..."
    for KeyValue (k, v) in (snd res) do
        printfn "(child, pr) -> (%s, %s)" k v
    printfn "Test finished: Path: %s | Success? ==> %b" path successful

(* Test test009 *)
if test009.Active then
    PrintTestHeader test009
    printfn "Defining nodes..."
    let nodeA = new NetworkNode ("Node A")
    let nodeB = new NetworkNode ("Node B")
    let nodeC = new NetworkNode ("Node C")
    let nodeD = new NetworkNode ("Node D")
    let nodeE = new NetworkNode ("Node E")
    printfn "Setting neighbourhood..."
    nodeA.AddNeighbour (nodeB, 10.0)
    nodeB.AddNeighbour (nodeC, 10.0)
    nodeC.AddNeighbour (nodeD, 10.0)
    nodeE.AddNeighbour (nodeD, 10.0)
    printfn "Network set! Listing nodes..."
    printfn "- Node -> %s" (nodeA.ToString ())
    printfn "- Node -> %s" (nodeB.ToString ())
    printfn "- Node -> %s" (nodeC.ToString ())
    printfn "- Node -> %s" (nodeD.ToString ())
    printfn "- Node -> %s" (nodeE.ToString ())
    printfn "Working..."
    let res = AStar nodeA nodeE
    let path = (PrintPath "" (RebuildPath [] (snd res) nodeE.Name))
    let successful = CheckPath test009.CorrectPath path
    test009.Result <- Some successful
    printfn "Showing parental directions..."
    for KeyValue (k, v) in (snd res) do
        printfn "(child, pr) -> (%s, %s)" k v
    printfn "Test finished: Path: %s | Success? ==> %b" path successful

(* Test test010 *)
if test010.Active then
    PrintTestHeader test010
    printfn "Defining nodes..."
    let nodeA = new NetworkNode ("Node A")
    let nodeB = new NetworkNode ("Node B")
    let nodeC = new NetworkNode ("Node C")
    let nodeD = new NetworkNode ("Node D")
    let nodeE = new NetworkNode ("Node E")
    let nodeF = new NetworkNode ("Node F")
    printfn "Setting neighbourhood..."
    nodeA.AddNeighbour (nodeB, 10.0)
    nodeB.AddNeighbour (nodeC, 10.0)
    nodeC.AddNeighbour (nodeD, 10.0)
    nodeD.AddNeighbour (nodeE, 10.0)
    nodeE.AddNeighbour (nodeA, 10.0)
    nodeF.AddNeighbour (nodeA, 50.0)
    nodeF.AddNeighbour (nodeB, 50.0)
    nodeF.AddNeighbour (nodeC, 50.0)
    nodeF.AddNeighbour (nodeD, 50.0)
    nodeF.AddNeighbour (nodeE, 50.0)
    printfn "Network set! Listing nodes..."
    printfn "- Node -> %s" (nodeA.ToString ())
    printfn "- Node -> %s" (nodeB.ToString ())
    printfn "- Node -> %s" (nodeC.ToString ())
    printfn "- Node -> %s" (nodeD.ToString ())
    printfn "- Node -> %s" (nodeE.ToString ())
    printfn "- Node -> %s" (nodeF.ToString ())
    printfn "Working..."
    let res = AStar nodeA nodeF
    let path = (PrintPath "" (RebuildPath [] (snd res) nodeF.Name))
    let successful = CheckPath test010.CorrectPath path
    test010.Result <- Some successful
    printfn "Showing parental directions..."
    for KeyValue (k, v) in (snd res) do
        printfn "(child, pr) -> (%s, %s)" k v
    printfn "Test finished: Path: %s | Success? ==> %b" path successful

(* Test test011 *)
if test011.Active then
    PrintTestHeader test011
    printfn "Defining nodes..."
    let nodeA = new NetworkNode ("Node A")
    let nodeB = new NetworkNode ("Node B")
    let nodeC = new NetworkNode ("Node C")
    let nodeD = new NetworkNode ("Node D")
    let nodeE = new NetworkNode ("Node E")
    let nodeF = new NetworkNode ("Node F")
    let nodeG = new NetworkNode ("Node G")
    printfn "Setting neighbourhood..."
    nodeA.AddNeighbour (nodeB, 20.0)
    nodeA.AddNeighbour (nodeE, 30.0)
    nodeB.AddNeighbour (nodeA, 10.0)
    nodeB.AddNeighbour (nodeC, 10.0)
    nodeB.AddNeighbour (nodeD, 100.0)
    nodeC.AddNeighbour (nodeF, 30.0)
    nodeF.AddNeighbour (nodeC, 10.0)
    nodeD.AddNeighbour (nodeA, 10.0)
    nodeD.AddNeighbour (nodeC, 10.0)
    nodeD.AddNeighbour (nodeE, 50.0)
    nodeD.AddNeighbour (nodeF, 50.0)
    nodeE.AddNeighbour (nodeA, 10.0)
    nodeG.AddNeighbour (nodeE, 30.0)
    nodeG.AddNeighbour (nodeD, 30.0)
    nodeG.AddNeighbour (nodeF, 30.0)
    printfn "Network set! Listing nodes..."
    printfn "- Node -> %s" (nodeA.ToString ())
    printfn "- Node -> %s" (nodeB.ToString ())
    printfn "- Node -> %s" (nodeC.ToString ())
    printfn "- Node -> %s" (nodeD.ToString ())
    printfn "- Node -> %s" (nodeE.ToString ())
    printfn "- Node -> %s" (nodeF.ToString ())
    printfn "- Node -> %s" (nodeG.ToString ())
    printfn "Working..."
    let res = AStar nodeA nodeG
    let path = (PrintPath "" (RebuildPath [] (snd res) nodeG.Name))
    let successful = CheckPath test011.CorrectPath path
    test011.Result <- Some successful
    printfn "Showing parental directions..."
    for KeyValue (k, v) in (snd res) do
        printfn "(child, pr) -> (%s, %s)" k v
    printfn "Test finished: Path: %s | Success? ==> %b" path successful

(* Test test012 *)
if test012.Active then
    PrintTestHeader test012
    printfn "Defining nodes..."
    let nodeA = new NetworkNode ("Node A")
    let nodeB = new NetworkNode ("Node B")
    let nodeC = new NetworkNode ("Node C")
    let nodeD = new NetworkNode ("Node D")
    let nodeE = new NetworkNode ("Node E")
    printfn "Setting neighbourhood..."
    nodeA.AddNeighbour (nodeB, 10.0)
    nodeA.AddNeighbour (nodeC, 10.0)
    nodeA.AddNeighbour (nodeD, 10.0)
    nodeE.AddNeighbour (nodeB, 10.0)
    nodeE.AddNeighbour (nodeC, 10.0)
    nodeE.AddNeighbour (nodeD, 10.0)
    printfn "Network set! Listing nodes..."
    printfn "- Node -> %s" (nodeA.ToString ())
    printfn "- Node -> %s" (nodeB.ToString ())
    printfn "- Node -> %s" (nodeC.ToString ())
    printfn "- Node -> %s" (nodeD.ToString ())
    printfn "- Node -> %s" (nodeE.ToString ())
    printfn "Working..."
    let res = AStar nodeA nodeE
    let path = (PrintPath "" (RebuildPath [] (snd res) nodeE.Name))
    let successful = CheckPath test012.CorrectPath path
    test012.Result <- Some successful
    printfn "Showing parental directions..."
    for KeyValue (k, v) in (snd res) do
        printfn "(child, pr) -> (%s, %s)" k v
    printfn "Test finished: Path: %s | Success? ==> %b" path successful

(* Summarizing *)
printfn "************************************************************************************"
printfn "------------------------------------------------------------------------------------"
printfn "TEST SUMMARY:"
printfn "Total tests: %d" tests.Length
for i in tests do
    match i.Result with
    | None -> printfn "Test %s/%s ==> NOT EXECUTED" i.Category i.Name
    | Some v -> printfn "Test %s/%s ==> %b" i.Category i.Name v
let rec overall_res lst =
    match lst with
    | [] -> true
    | h :: t -> 
        match h with 
        | None -> true && overall_res t
        | Some v -> v && overall_res t
printfn "TEST ENDED WITH OVERALL RESULT ==> %b" (List.map (fun x -> x.Result) tests |> overall_res)
printfn "------------------------------------------------------------------------------------"
printfn "************************************************************************************"
